package com.atguigu.product.products.web;


import com.atguigu.product.products.dao.PmsCategoryDao;
import com.atguigu.product.products.entity.PmsCategoryEntity;
import com.atguigu.product.products.service.PmsCategoryService;
import com.atguigu.product.products.service.PmsSkuInfoService;
import com.atguigu.product.products.vo.respVo.Catelog2Vo;
import com.atguigu.product.products.vo.respVo.item.SkuItemVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutionException;


/**
 * 商品html渲染信息
 *
 * @author qhw
 * @email qhw@gmail.com
 * @date 2021-08-03 19:57:10
 */
@Controller
public class PmsCategoryWeb {
    @Autowired
    private PmsCategoryDao pmsCategoryDao;
    @Autowired
    private PmsCategoryService pmsCategoryService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PmsSkuInfoService skuInfoService;

    @GetMapping({"/", "/index.html"})
    public String indexSource(Model model) {
        //做数据的渲染
        //查出所有的一级分类
        List<PmsCategoryEntity> categorys = pmsCategoryDao.selectList(new QueryWrapper<PmsCategoryEntity>().eq("parent_cid", 0));
        model.addAttribute("categorys", categorys);
        return "index";

    }

    @GetMapping("/{skuId}.html")
    public String item(@PathVariable("skuId") Long skuId,Model model) throws ExecutionException, InterruptedException {

        SkuItemVo skuItemVo = skuInfoService.item(skuId);
        model.addAttribute("item",skuItemVo);
        return "item";

    }

//    @GetMapping("/{skuId}.html")
//    public String skuItem(@PathVariable("skuId") Long skuId, Model model) throws ExecutionException, InterruptedException {
//
////        System.out.println("准备查询"+skuId+"详情");
////        SkuItemVo vo = skuInfoService.item(skuId);
////        model.addAttribute("item",vo);
//
//        return "item";
//    }
    @GetMapping("index/catalog.json")
    @ResponseBody
    public Map<String, List<Catelog2Vo>> indexCatelog() {
        Map<String, List<Catelog2Vo>> stringListMap = pmsCategoryService.indexCatelogRedis2();
        return stringListMap;

    }

    /**
     * 1.普通加锁-解锁
     *
     * @return
     */
    @GetMapping("test")
    @ResponseBody
    public String test() {
        System.out.println(1);
        //添加锁
        RLock lock = redissonClient.getLock("my-lock");

        //加锁--阻塞式等待操作--默认当业务超长时有自动续期的功能(看门狗机制)--当主从配置从机宕机后如果没有解锁一段时间后也会自动解锁
        lock.lock();
        try {
            //执行业务
            Thread.sleep(20000);
        } catch (Exception e) {

        } finally {
            //解锁
            lock.unlock();
        }

        return "ok" + Thread.currentThread().getId();
    }

    /**
     * 2.读写锁
     *
     * @return
     */
    @GetMapping("testWrite")
    @ResponseBody
    public String testWrite() {
        System.out.println(1);
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("wr-lock");

        //加锁--阻塞式等待操作--默认当业务超长时有自动续期的功能(看门狗机制)--当主从配置从机宕机后如果没有解锁一段时间后也会自动解锁
        RLock rLock = readWriteLock.writeLock();
        rLock.lock();
        String s = "";
        try {
            //执行业务
            s = UUID.randomUUID().toString();
            stringRedisTemplate.opsForValue().set("write", s);
            Thread.sleep(20000);
        } catch (Exception e) {

        } finally {
            //解锁
            rLock.unlock();
        }

        return s;
    }


    @GetMapping("testRead")
    @ResponseBody
    public String testRead() {
        System.out.println(1);
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("wr-lock");

        //加锁--阻塞式等待操作--默认当业务超长时有自动续期的功能(看门狗机制)--当主从配置从机宕机后如果没有解锁一段时间后也会自动解锁
        RLock rLock = readWriteLock.readLock();
        rLock.lock();
        String read = "";
        try {
            //执行业务
            read = stringRedisTemplate.opsForValue().get("write");
        } catch (Exception e) {

        } finally {
            //解锁
            rLock.unlock();
        }

        return read;
    }


    /**
     * 3.信号量，停车位，限流
     */

    @GetMapping("park")
    @ResponseBody
    public String park() {
        RSemaphore park = redissonClient.getSemaphore("park");
        //尝试获取信号量-非阻塞方法
        boolean b = park.tryAcquire();
        if (b) {
            //说明可以获取执行相关业务
        } else {
            return "error";
        }
        return "ok";
    }


    /**
     * 信号量，停车位，限流
     */

    @GetMapping("go")
    @ResponseBody
    public String go() {
        RSemaphore park = redissonClient.getSemaphore("park");
        //释放车位
        park.release();
        return "释放车位";

    }



    /**
     * 闭锁测试
     */

    @GetMapping("/lockDoor")
    @ResponseBody
    public String lockDoor() {
        RCountDownLatch lockDoor = redissonClient.getCountDownLatch("lockDoor");
        boolean b = lockDoor.trySetCount(3);
        if(b){
            return "error";
        }else {
            return "放假了";
        }

    }


    /**
     * 释放方法
     */

    @GetMapping("/gg/{id}")
    @ResponseBody
    public String gg(@PathVariable("id") Long id) {
        RCountDownLatch lockDoor = redissonClient.getCountDownLatch("lockDoor");
        lockDoor.countDown();//计数减一

        return "几班的人走了"+id;

    }
}
